package hyl.core.run;

import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import hyl.core.Amy;
import hyl.core.MyFun;
import hyl.core.io.MyFile;

/**
 * MyRun 线程控制器 Schedule 是定时任务线程
 */
public class MyRun extends AExecute {
	public static final Logger Log = LoggerFactory.getLogger(MyRun.class);
	protected static int MAXNUM = 1024;
	protected static Map<String, MyRun> servicemap = new ConcurrentHashMap<>();
	static final int cmd超时毫秒 = 60000;

	public static void closeAll() {
		for (String key : servicemap.keySet()) {
			MyRun ss = servicemap.get(key);
			ss.close();
		}
		servicemap.clear();
	}

	public static void close(String servicename) {
		MyRun ss = servicemap.get(servicename);
		if (ss == null)
			return;
		ss.close();
		servicemap.remove(servicename);
	}

	protected ExecutorService _es;

	/**
	 * 适用于生产环境
	 */
	public void close() {
		close(_es);
		Log.info(_name + "线程池已关闭");
	}

	/**
	 * 适用于test环境 因为junit 的线程 是非守护线程
	 */
	public void waitAndClose() {
		try {
			waitAndClose(_es);
			Log.info(_name + "线程池已清空并关闭");
		} catch (InterruptedException e) {
			Log.info(_name + "线程池中断出现异常");
			e.printStackTrace();
		}
	}

	private MyRun(String servicename, ExecutorService es) {
		_name = servicename;
		_es = es;
	}

	/*
	 * 不可以外露 public ExecutorService getExecutorService() { return _es; }
	 */
	public static MyRun getInstance(String servicename) {
		return getInstance(servicename, 1);
	}

	/**
	 * 
	 * @param servicename
	 * @param threadnum   0:newCachedThreadPool ; 1 :newSingleThreadExecutor; 其他
	 *                    ：newFixedThreadPool
	 * @return
	 */
	public static MyRun getInstance(String servicename, Integer threadnum) {
		if (servicemap.containsKey(servicename))
			return servicemap.get(servicename);
		ExecutorService es = null;

		if (threadnum == 0) {
			es = Executors.newCachedThreadPool();
		} else if (threadnum == 1) {
			es = Executors.newSingleThreadExecutor();
		} else {
			if (threadnum == null || MAXNUM < threadnum || threadnum < 0)
				threadnum = MAXNUM;
			es = Executors.newFixedThreadPool(threadnum);
		}
		MyRun mr = new MyRun(servicename, es);
		// 所有线程统一管理,不同的服务名称,对应不同的线程组
		servicemap.put(servicename, mr);
		return mr;
	}

	/** 线程同步执行 Callable 为待执行的方法 */
	public <T> T call(Callable<T> call) {
		Future<T> v = _es.submit(call); // 可以取到正确的值
		try {
			return v.get();
		} catch (Exception e) {
			return null;
		}
	}

	/** 线程同步执行 */
	public boolean call(Runnable run) {
		Future<?> v = _es.submit(run); // 可以取到正确的值
		try {
			if (v.get() == null)
				return true;
			else
				return false;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 线程同步执行,不常用 Callable 为待执行的方法 用法 ： v1=submit（callable1） v2=submit（callable2）
	 * 
	 * if（v1.get（）+v2.get（）==3） 完成。。。
	 * 
	 * 
	 */
	public <T> Future<T> submit(Callable<T> call) {
		return _es.submit(call);
	}

	public Future<?> submit(Runnable call) {
		return _es.submit(call);
	}

	/** 线程异步执行 */
	public void execute(Runnable run) {
		_es.execute(run); // 可以取到正确的值

	}

	/** 执行cmd命令 带参数的，获取返回结果 */
	public static String cmd(String[] command, int timeout) {

		try {
			Process p = process(command);
			return 执行(p, timeout);
		} catch (Exception e) {
			return e.toString();
		}
	}

	/**
	 * 默认超时 是15s
	 * 
	 * @param command
	 * @return
	 */
	public static String cmd(String command) {
		return cmd(command, cmd超时毫秒);
	}

	/**
	 * cmd /c "指令" 执行cmd命令不带参数的， 获取返回结果
	 */
	public static String cmd(String command, int timeout) {
		try {
			Process p = process(command);
			return 执行(p, timeout);
		} catch (Exception e) {
			return e.toString();
		}
	}

	static String 执行(Process process, int 超时) {
		StringBuffer sb = new StringBuffer();

		new Thread(new Runnable() {
			public void run() {
				try {
					String s = MyFile.read(process.getInputStream());
					// System.out.println("11"+s);
					if (!MyFun.isEmpty(s))
						sb.append(s);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		// 启动单独的线程来清空p.getInputStream()的缓冲区

		new Thread(new Runnable() {
			public void run() {
				try {
					String s = MyFile.read(process.getErrorStream());
					// System.out.println("22"+s);
					if (!MyFun.isEmpty(s))
						sb.append(s);
				} catch (Exception e) {
					e.printStackTrace();
				}

			}

		}).start();
		try {

			// 等待时间超过 限制 返回false
			if (!process.waitFor(超时, TimeUnit.MILLISECONDS)) {
				// System.out.println("33超时");
				sb.insert(0, "超时!");
			}
		} catch (InterruptedException e) {
			return e.getMessage();
		}
		// System.out.println("44"+sb.toString());
		process.destroy();
		return sb.toString();
	}

	/**
	 * 默认超时15s
	 * 
	 * @param command
	 * @return
	 */
	public static boolean exec(String command) {
		return exec(command, cmd超时毫秒);
	}

	/**
	 * 执行exec命令不带参数，如果异常返回false
	 * 
	 * @param command
	 * @param timeout 超时限制 (单位: 毫秒)
	 * @return
	 */
	public static boolean exec(String command, int timeout) {
		Process p = null;
		boolean result = false;
		try {

			// 获取当前进程的信息
//			RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
//			System.err.println(rt.getLibraryPath());

			// 截取进程id
			// Runtime.getRuntime().

			p = process(command);
			if (p.waitFor(timeout, TimeUnit.MILLISECONDS)) {
				result = true;
			}
		} catch (Exception e) {
			Log.error("异常:", e);
		} finally {
			p.destroy();
		}
		return result;
	}

	/**
	 * 执行exec命令 返回执行进程句柄
	 * 
	 * @throws IOException
	 */
	private static Process process(String command) throws IOException {
		// Log.info(command);
		return Runtime.getRuntime().exec(command);
	}

	private static Process process(String[] command) throws IOException {

		return Runtime.getRuntime().exec(command);
	}

	/**
	 * 检测程序。 "TASKLIST /FI \"IMAGENAME eq " + processName + "\""
	 * 
	 * @param processName 线程的名字，请使用准确的名字
	 * @return 找到返回true,没找到返回false
	 */

	/**
	 * 强行关闭外部线程
	 * 
	 * @param stopthreads
	 */
	@SuppressWarnings("deprecation")
	public static void close外部线程(String[] stopthreads) {
		final Set<Thread> threads = Thread.getAllStackTraces().keySet();
		for (Thread thread : threads) {
			for (String s : stopthreads)
				if (s.startsWith(thread.getName())) {
					try {
						// thread.interrupt();
						/*
						 * thread.join();
						 */
						thread.stop();
						Amy.Log.info(String.format("释放  %s successful", thread));
					} catch (Exception e) {
						Amy.Log.info(String.format("释放 %s error", thread), e);
					}
				}
		}
	}
}
